package cn.com.netedge.iot.frontend.biz.task;

import cn.com.netedge.iot.common.constants.CacheKeyConstants;
import cn.com.netedge.iot.common.dataobject.DeviceRunningInfo;
import cn.com.netedge.iot.common.enums.OnlineStatusEnum;
import cn.com.netedge.iot.common.utils.DateUtil;
import cn.com.netedge.iot.common.utils.RedisUtil;
import cn.com.netedge.iot.common.utils.StringUtil;
import cn.com.netedge.iot.frontend.biz.config.BpConfig;
import com.alibaba.fastjson2.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class FixDelayTask {
    private static Logger logger = LoggerFactory.getLogger(FixDelayTask.class);
    private final static int LENGTH_MIN = 12;
    private static final int HEART_BEAT_INTERVAL = 30 * 1000; // 30 秒
    private static final int DEVICE_TYPE_METER = 0;

    @Scheduled(fixedDelay = HEART_BEAT_INTERVAL)
    public void hearBeat() {
        if (StringUtil.isEmpty(BpConfig.getMachineName())) {
            logger.info("machine name is empty.");
            return;
        }
        Date now = new Date();
        RedisUtil.hset(CacheKeyConstants.KEY_FRONTEND_BIZ_MACHINE + "machine_map", BpConfig.getMachineName(), DateUtil.DateToLongStr(now));
    }

    /**
     * 遍历实时或定时任务队列
     */
    @Scheduled(fixedDelay = 10)
    public void traverseTaskQueue() {
        if (!isLeader()) {
            return;
        }
        String key = CacheKeyConstants.KEY_DEVICE_RUNNING + "map";
        Set<String> deviceKeys = RedisUtil.hkeys(key);
        if (deviceKeys == null || deviceKeys.isEmpty()) {
            //logger.info("{} 's key list is empty.", key);
            return;
        }
        for (String deviceKey : deviceKeys) {
            String value = RedisUtil.get(deviceKey);
            if (StringUtil.isEmpty(value)) {
                //logger.debug("{} value is empty.", deviceKey);
                continue;
            }
            DeviceRunningInfo info = JSON.parseObject(value, DeviceRunningInfo.class);
            if (info == null) {
                //logger.debug("{} value can't convert to DeviceRunningInfo.", deviceKey);
                continue;
            }
            if (info.getCurStatus() == OnlineStatusEnum.OFFLINE.getCode()) {
                //logger.debug("{} is offline.", deviceKey);
                continue;
            }
            String deviceNumber = info.getDeviceNumber();
            int deviceType = info.getDeviceType();
//            processTask(deviceNumber, deviceType);
        }
    }


    /**
     * 判断自己是否为领导，最小序号节点名与机器名是否相同
     *
     * @return
     */
    private static boolean isLeader() {
        String key = CacheKeyConstants.KEY_FRONTEND_BIZ_MACHINE + "machine_map";
        Set<String> machineNameList = RedisUtil.hkeys(key);
        if (machineNameList == null || machineNameList.isEmpty()) {
            //logger.info("{} 's name list is empty.", key);
            return false;
        }
        List<String> children = new ArrayList<>(machineNameList.size());
        Date now = new Date();
        Date compareTime = DateUtil.addMilliseconds(now, -(HEART_BEAT_INTERVAL * 3));
        String value;
        Date hearBeatTime;
        for (String machineName : machineNameList) {
            value = RedisUtil.hget(key, machineName);
            if (StringUtil.isEmpty(value)) {
                //logger.info("machine:{} 's heartbeat time is null.", machineName);
                continue;
            }
            hearBeatTime = DateUtil.LongStrToDate(value);
            if (hearBeatTime == null) {
                //logger.info("value:{} can't convert date.", value);
                continue;
            }
            if (hearBeatTime.after(compareTime)) { //离线
                //logger.debug("machine:{} --> online.", machineName);
                children.add(machineName);
                continue;
            }
            RedisUtil.hdel(key, machineName);
        }
        if (children.size() > 0) {
            Collections.sort(children);
            String leader = children.get(0);
            if (leader == null || !leader.equals(BpConfig.getMachineName())) {
                return false;
            }
        }
        return true;
    }
}
